package com.bdqn.controller;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.bdqn.common.Constants;
import com.bdqn.common.PageSupport;
import com.bdqn.pojo.SysRole;
import com.bdqn.pojo.SysUser;
import com.bdqn.service.SysRoleService;
import com.bdqn.service.SysUserService;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.lang.math.RandomUtils;
import org.apache.log4j.Logger;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;

/**
 * SysUserController
 *
 * @author LILIBO
 * @since 2021-11-04
 */
@Controller
@RequestMapping("/user")
public class SysUserController {

    private Logger logger = Logger.getLogger(SysUserController.class);

    @Resource
    SysUserService sysUserService;

    @Resource
    SysRoleService sysRoleService;

    @GetMapping("/login")
    public String toLogin() {
        logger.debug("跳转到登录页面");
        return "login";
    }

    @GetMapping("/frame")
    public String toFrame(HttpSession session) {
        logger.debug("跳转到后台主页");
        // 去到后台主页，但是必须是已经登录的用户
        if (session.getAttribute("USER_SESSION") == null) {
            return "redirect:/user/login";
        }
        return "frame";
    }

    @PostMapping("/login")
    public String doLogin(Model model, HttpSession session, @RequestParam String account, @RequestParam String password) {
        logger.debug("处理登录请求 --> account: " + account + " password: " + password);
        SysUser sysUser = sysUserService.login(account, password);
        // if (sysUser == null) {
        //     model.addAttribute("error", "账号或密码错误");
        //     return "login"; // 登录失败，跳转回登录页面
        // }
        if (sysUser == null) {
            throw new RuntimeException("账号或密码错误");
        }

        // 数据库账号密码匹配成功之后，将用户对象保存到Session作用域中
        session.setAttribute("USER_SESSION", sysUser);

        return "redirect:/user/frame"; // 登录成功，跳转到后台页面
    }

    @GetMapping("/logout")
    public String logout(HttpSession session) {
        logger.debug("退出登录");
        // 清除当前登录用户的Session
        session.removeAttribute("USER_SESSION");
        session.invalidate(); // 销毁Session

        return "redirect:/user/login";
    }

    @GetMapping("/list")
    public String list(Model model, @RequestParam(required = false) String queryRealName, @RequestParam(required = false) Long queryRoleId, @RequestParam(required = false, defaultValue = "1") Integer pageIndex) {
        logger.debug("查询用户列表");
        // 页面查询条件数据回显（使用的查询条件在查到数据之后需要继续保留在页面输入框中）
        model.addAttribute("queryRealName", queryRealName);
        model.addAttribute("queryRoleId", queryRoleId);

        // 从服务层获取角色集合数据
        List<SysRole> sysRoleList = sysRoleService.getList(null);
        // 将角色列表放入Page作用域，页面通过roleList使用
        model.addAttribute("roleList", sysRoleList);

        // 页面传递过来的查询条件通过SysUser对象封装
        SysUser sysUser = new SysUser();
        sysUser.setRoleId(queryRoleId);
        sysUser.setRealName(queryRealName);

        // 实例化分页查询工具类
        PageSupport page = new PageSupport();
        // 首先使用和查询相同的条件获得总记录数
        page.setTotalCount(sysUserService.getPageListTotal(sysUser)); // 获得总记录数并设置在分页对象中
        page.setCurrentPageNo(pageIndex); // 当前页

        // 查询分页数据
        List<SysUser> sysUserList = sysUserService.getPageList(sysUser, page);
        model.addAttribute("userList", sysUserList);

        // 设置分页信息
        model.addAttribute("page", page);
        return "sysUser/list";
    }

    @ResponseBody // 直接将数据响应（通常使用Ajax调用时要加该注解）
    @DeleteMapping("/del/{userId}")
    public String del(@PathVariable("userId") Long userId) {
        SysUser sysUser = sysUserService.getById(userId);
        boolean delok = false;
        if (sysUser != null) {
            delok = sysUserService.delById(userId);
            System.out.println(delok);

            return "{\"delResult\":\"" + delok + "\"}";
        } else {
            return "{\"delResult\":\"notexist\"}";
        }
    }

    /**
     * 跳转到添加用户页面
     *
     * @return
     */
    @GetMapping("/add")
    public String toAdd(HttpServletRequest request) {
        logger.debug("去到添加页面");
        // 从服务层拿到角色数据
        List<SysRole> roleList = sysRoleService.getList(null);
        // 将角色列表放入Request作用域，页面通过roleList使用
        request.setAttribute("roleList", roleList);
        return "sysUser/add";
    }

    /**
     * 验证账号是否已存在
     *
     * @param account
     * @return
     */
    @ResponseBody // 将返回的内容写入body区域
    @GetMapping(value = "/userExist", produces = "text/html;charset=UTF-8")
    public String userExist(@RequestParam String account) {
        logger.debug("验证用户【account=" + account + "】是否存在");
        HashMap<String, Object> resultMap = new HashMap<>();
        if (StringUtils.isEmpty(account)) {
            resultMap.put("exist", 1);
        } else {
            SysUser sysUser = sysUserService.getAccountExist(account);
            if (sysUser != null) {
                resultMap.put("exist", 1); // 已存在，不能使用
            } else {
                resultMap.put("exist", 0); // 不存在，可以使用
            }
        }
        return JSON.toJSONString(resultMap); // {"exist":"1"}
    }

    /**
     * 添加用户
     *
     * @param sysUser
     * @param session
     * @return
     */
    @PostMapping("/add")
    public String add(SysUser sysUser, HttpServletRequest request, HttpSession session, @RequestParam(value = "idPic", required = false) MultipartFile idPic, @RequestParam(value = "workPic", required = false) MultipartFile workPic) {
        /*public String add(SysUser sysUser, HttpServletRequest request, HttpSession session, @RequestParam(value = "attachs", required = false) MultipartFile[] attachs) {*/

        // 定义文件存放目录
        String uploadPath = request.getSession().getServletContext().getRealPath(Constants.UPLOAD_PATH);

        // 从上传的文件列表中获得第1个文件
        // MultipartFile idPic = attachs[0]; // 获得上传的证件照图片
        // 证件照图片文件上传，成功后返回地址
        String idPicPath = multipartFileUpload(uploadPath, request, idPic); // 调用文件上传方法，成功则返回上传地址
        if (idPicPath == null) {
            String uploadFileError = (String) request.getAttribute("uploadFileError");
            request.setAttribute("idPicUploadError", uploadFileError);
            request.removeAttribute("uploadFileError"); // 临时使用，使用完毕后移除信息
            return "sysUser/add";
        } else {
            // 设置身份证照片地址
            sysUser.setIdPicPath(idPicPath);
        }

        // 从上传的文件列表中获得第2个文件
        // MultipartFile workPic = attachs[1]; // 获得上传的工作照图片
        // 工作照图片文件上传，成功后返回地址
        String workPicPath = multipartFileUpload(uploadPath, request, workPic); // 调用文件上传方法，成功则返回上传地址
        if (idPicPath == null) {
            String uploadFileError = (String) request.getAttribute("uploadFileError");
            request.setAttribute("workPicUploadError", uploadFileError);
            request.removeAttribute("uploadFileError"); // 临时使用，使用完毕后移除信息
            return "sysUser/add";
        } else {
            // 设置工作证照片地址
            sysUser.setWorkPicPath(workPicPath);
        }

        // 设置操作者ID
        SysUser loginUser = (SysUser) session.getAttribute(Constants.USER_SESSION);
        sysUser.setCreatedUserId(loginUser.getId());
        if (sysUserService.add(sysUser)) {
            return "redirect:/user/list";
        }
        return "sysUser/add";
    }

    /**
     * 多部件文件上传（错误信息临时保存在request作用域uploadFileError属性中）
     *
     * @return 成功返回文件上传地址，返回null表示文件上传失败
     */
    public String multipartFileUpload(String uploadPath, HttpServletRequest request, MultipartFile multipartFile) {
        String uploadFilePath = null; // 文件上传地址，返回null表示文件上传失败

        // 定义文件存放目录
        logger.debug("上传文件路径：" + uploadPath);

        if (!multipartFile.isEmpty()) {
            // 获取上传的文件信息
            String originalFile = multipartFile.getOriginalFilename(); // 原文件名称
            logger.debug("原文件名称为：" + originalFile);
            String prefix = FilenameUtils.getExtension(originalFile); // 原文件后缀
            logger.debug("原文件后缀为：" + prefix);
            long fileSize = multipartFile.getSize(); // 原文件大小
            logger.debug("上传文件大小：" + fileSize);

            // 判断上传的文件是否符合要求
            if (fileSize > Constants.MAX_FILE_SIZE) { // 上传文件大小不能超过500KB
                request.setAttribute("uploadFileError", " * 上传文件大小不得超过 500KB");
                return uploadFilePath;
            }
            if (!(prefix.equalsIgnoreCase("jpg") || prefix.equalsIgnoreCase("jpeg") || prefix.equalsIgnoreCase("png") || prefix.equalsIgnoreCase("pneg"))) {
                request.setAttribute("uploadFileError", " * 上传文件格式只能是jpg、jpeg、png、pneg");
                return uploadFilePath;
            }

            // 确定文件存储名称
            String fileName = System.currentTimeMillis() + RandomUtils.nextInt(1000) + "_Personal." + prefix;
            logger.debug("新生成的文件名为：" + fileName);

            // 将上传的文件保存到目标位置
            File targetFile = new File(uploadPath);
            if (!targetFile.exists()) {
                targetFile.mkdirs(); // 如果目录不存在则生成目录
            }
            // 保存文件
            try {
                // 存储物理地址 + 生成的文件名称
                multipartFile.transferTo(new File(targetFile, fileName));
            } catch (IOException e) {
                e.printStackTrace();
                request.setAttribute("uploadFileError", " * 文件上传失败！");
                return uploadFilePath;
            }
            // 文件上传完成就可以拿到地址
            uploadFilePath = File.separator + Constants.UPLOAD_PATH + File.separator + fileName;
        }

        // 返回文件上传成功后的地址，失败时返回null，并且将失败信息记录到
        return uploadFilePath;
    }

    /**
     * 查询用户详情
     *
     * @param id
     * @param model
     * @return
     */
    @GetMapping("/view/{id}")
    public String view(@PathVariable Long id, Model model) {
        logger.debug("根据id查询用户详情：" + id);
        SysUser sysUser = sysUserService.getById(id);
        model.addAttribute(sysUser);
        return "sysUser/view";
    }

    /**
     * 局部刷新显示用户详情
     *
     * @param id
     * @return
     */
    @ResponseBody // 将返回内容直接写入body块
    @GetMapping("/{id}/view") // produces = {"application/json;charset=UTF-8"} 指定返回内容的编码类型
    public Object view(@PathVariable String id) {
        logger.debug("查询用户详情【id="+id+"】");
        String sysUserJSON = "failed";
        if (StringUtils.isEmpty(id)) {
            return "nodata";
        }
        SysUser sysUser = sysUserService.getById(Long.parseLong(id));
        if (sysUser != null) {
            JSONObject.DEFFAULT_DATE_FORMAT = "yyyy-MM-dd";
            sysUserJSON = JSON.toJSONString(sysUser);
        } else {
            return "nodata";
        }
        return sysUserJSON;
    }

    /**
     * 局部刷新显示用户详情
     *
     * @param id
     * @return
     */
    @ResponseBody // 将返回内容直接写入body块
    @GetMapping(value = "/{id}/view.json", produces = {"application/json;charset=UTF-8"}) // produces = {"application/json;charset=UTF-8"} 指定返回内容的编码类型
    public Object view(@PathVariable Long id) {
        logger.debug("查询用户详情【id="+id+"】");
        String sysUserJSON = "failed";
        if (StringUtils.isEmpty(id)) {
            return "nodata";
        }
        SysUser sysUser = sysUserService.getById(id);
        if (sysUser != null) {
            JSONObject.DEFFAULT_DATE_FORMAT = "yyyy-MM-dd";
            sysUserJSON = JSON.toJSONString(sysUser);
        } else {
            return "nodata";
        }
        return sysUserJSON;
    }

    /**
     * 局部刷新显示用户详情
     *
     * @param id
     * @return
     */
    @ResponseBody // 将返回内容直接写入body块
    @GetMapping(value = "/{id}/view.xml", produces = {"application/xml;charset=UTF-8"}) // produces = {"application/json;charset=UTF-8"} 指定返回内容的编码类型
    public Object viewXML(@PathVariable Long id) {
        logger.debug("查询用户详情【id="+id+"】");
        String sysUserJSON = "failed";
        if (StringUtils.isEmpty(id)) {
            return "nodata";
        }
        SysUser sysUser = sysUserService.getById(id);
        if (sysUser != null) {
            JSONObject.DEFFAULT_DATE_FORMAT = "yyyy-MM-dd";
            sysUserJSON = ""; // 转换为XML格式
        } else {
            return "nodata";
        }
        return sysUserJSON;
    }

    /**
     * 跳转到修改页面
     *
     * @param uid
     * @param model
     * @return
     */
    @GetMapping("/toUpdate")
    public String toUpdate(@RequestParam Long uid, Model model) {
        logger.debug("跳转到修改用户信息页面");
        SysUser sysUser = sysUserService.getById(uid);
        model.addAttribute(sysUser);
        return "sysUser/update";
    }

    /**
     * 执行修改操作
     *
     * @param sysUser
     * @param session
     * @return
     */
    @PostMapping("/update")
    public String update(SysUser sysUser, HttpSession session) {
        logger.debug("修改用户信息");
        SysUser loginUser = (SysUser) session.getAttribute(Constants.USER_SESSION);
        sysUser.setUpdatedUserId(loginUser.getId());
        if (sysUserService.update(sysUser)) {
            return "redirect:/user/list";
        }
        return "sysUser/update";
    }

    /**
     * 一个抛出异常的接口
     *
     * @param account
     * @param password
     * @return
     */
    @RequestMapping("/exlogin")
    public String exLogin(@RequestParam String account, @RequestParam String password) {
        logger.debug("一个抛出异常的接口");
        // 调用service方法，进行用户匹配
        SysUser sysUser = sysUserService.login(account, password);
        if (sysUser == null) {
            // 登录失败
            throw new RuntimeException("用户名或者密码不正确，跳转到错误页面！");
        }
        return "redirect:/user/toMain";
    }

    /**
     * 局部异常处理器
     *
     * @param e
     * @param request
     * @return
     */
    // @ExceptionHandler({RuntimeException.class})
    public String handlerException(RuntimeException e, HttpServletRequest request) {
        request.setAttribute("e", e);
        return "error";
    }

}
